/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Conexao;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;


import Opcoes.*;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.SocketException;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

    /**
    *
    *
    *@param Recebe como parâmetro o executorService e o gerenciador como parâmetros(referência), esta classe é utilizada para receber conexões de clientes
    *
    *
    **/

public class FluxoServer implements Runnable {

    private ExecutorService exec;
    private Gerenciador gerenciador;
    private ServerSocket serverSocket;
    private Socket socket;
    private DataInputStream in;
    private DataOutputStream out;
    private String msg;
    private boolean done;
    
    public FluxoServer(ExecutorService apps, Gerenciador ger) {

        this.exec = apps;
        this.gerenciador = ger;
        done = false;
    }

    public void done ()
    {
        done = true;
    }

    public void run() {

        StringTokenizer token;

        try {

            serverSocket = new ServerSocket(Conexoes.CONNECT_PORT);
        } catch (IOException ex) {
            System.out.println("Porta em uso!");
            System.out.println("Abortando Fluxos de Servidor!");
            done = true;
        }
        
        while(!done)
        {
            try {
                    
                System.out.println("SERVIDOR:Listening...");
                socket = serverSocket.accept();

                in = new DataInputStream(socket.getInputStream());
                out = new DataOutputStream(socket.getOutputStream());

                msg = in.readUTF();

                //System.out.println("MSG: " + msg);

                if (msg.startsWith(Conexoes.CONNECT_MSG.substring(0, 20)))
                {
                    System.out.printf("SERVIDOR:\nHOST:%s\tMSG:%s\n",socket.getInetAddress().toString(),msg);

                    if(this.gerenciador.setSockets(socket))
                        System.out.println("Novo servente conectado!");
                    else
                    {
                        socket.close();
                        System.out.println("Nuvem cheia, desconectando servente");
                    }

                    System.out.printf("Sending OK...\n");
                    out.writeUTF(Conexoes.CONNECT_OK);
                }else if (msg.startsWith("GET"))
                {
                    File arquivo;
                    byte[] arquivo_buffer;
                    FileInputStream fileInput;

                    String fileName;
                    String fileIndex;
                    int fileSize = 0;

                    token = new StringTokenizer(msg,"/");
                    token.nextToken();
                    token.nextToken();

                    fileIndex = token.nextToken(); // File Index
                    fileName = token.nextToken(); // File Name

                    // (!token.nextToken().matches(""))

                    arquivo = new File("Downloads/"+fileName);
                    fileInput = new FileInputStream(arquivo);
                    fileSize = (int)arquivo.length();
                    arquivo_buffer = new byte[fileSize];
                    fileInput.read(arquivo_buffer);

                    msg = "HTTP 200 OK\r\n" +
                            "Server: Gnutella\r\n" +
                            "Content-type: application/binary\r\n" +
                            "Content-length: " + fileSize + "\r\n" +
                            "\r\n";

                    out.writeUTF(msg);
                    out.flush();

                    
                    out.write(arquivo_buffer);
                    
                    System.out.println("Sent...\n");
                    socket.close();


                }
                else if (msg.startsWith("GIV"))
                {
                    token = new StringTokenizer(msg);
                    System.out.println(token.nextToken("GIV"));
                    System.out.println(token.nextToken("/"));
                    System.out.println(token.nextToken("/"));
                }

                //  GIV <File Index>:<Servent Identifier>/<File Name>\n\n

                //  GET /get/<File Index>/<File Name>/ HTTP/1.0\r\n
                //  Connection: Keep-Alive\r\n
                //  Range: bytes=0-\r\n
                //  User-Agent: Gnutella\r\n3
                //  \r\n

                //  HTTP 200 OK\r\n
                //  Server: Gnutella\r\n
                //  Content-type: application/binary\r\n
                //  Content-length: 4356789\r\n
                //  \r\n


            } catch (SocketException e) {
                System.out.println("SERVIDOR:Conexao Recusada!");
            } catch (IOException e) {
                System.out.println("SERVIDOR:Could not listen on port: 3333");
                e.printStackTrace();
            }
        
        }
    }

    public void encerrar() throws IOException {

        serverSocket.close();
        System.out.println("Servidor: CLOSED!");
        exec.shutdown();

    }

}
